#pragma once
#include "rpc_register.hpp"
#include "rpc_topic.hpp"
#include "../common/dispatcher.hpp"
#include "../server/rpc_router.hpp"
#include "../client/client.hpp"

namespace qiangsir
{
    namespace server
    {

        // 注册中心
        class RegistryServer
        {
        public:
            using ptr = std::shared_ptr<RegistryServer>;
            RegistryServer(int port)
                : _pdmanager(std::make_shared<PDMananger>()),
                  _dispather(std::make_shared<Dispatcher>())
            {
                auto req_cb = std::bind(&PDMananger::onServiceRequest, _pdmanager.get(),
                                        std::placeholders::_1, std::placeholders::_2);
                _dispather->registerHandler<ServiceRequest>(MType::REQ_SERVERICE, req_cb);

                auto msg_cb = std::bind(&Dispatcher::onMessage, _dispather.get(),
                                        std::placeholders::_1, std::placeholders::_2);
                _server = ServerFactory::create(port);
                _server->setMessageCallBack(msg_cb);

                auto close_cb = std::bind(&RegistryServer::shutDownCallBack, this, std::placeholders::_1);
                _server->setCloseCallBack(close_cb);
            }
            void start()
            {
                _server->start();
            }

        private:
            void shutDownCallBack(const BaseConnection::ptr &conn)
            {
                _pdmanager->onConnectionRequest(conn);
            }

        private:
            PDMananger::ptr _pdmanager;
            Dispatcher::ptr _dispather;
            BaseServer::ptr _server;
        };

        class RpcServer
        {
        public:
            using ptr = std::shared_ptr<RpcServer>;
            // 1.rpc访问地址
            // 2.注册中心地址
            RpcServer(const Address &rpc_addr, bool enableRegisry = false,
                      const Address &registry_addr = Address())
                : _enableRegistry(enableRegisry),
                  _dispather(std::make_shared<Dispatcher>()),
                  _router(std::make_shared<RpcRouter>()),
                  _rpc_addr(rpc_addr)
            {
                if (_enableRegistry)
                {
                    _registry_client = std::make_shared<client::RegistryClient>(registry_addr.first, registry_addr.second);
                }
                auto rpc_cb = std::bind(&RpcRouter::onRpcRequest, _router.get(),
                                        std::placeholders::_1, std::placeholders::_2);
                _dispather->registerHandler<RpcRequest>(MType::REQ_RPC, rpc_cb);
                _server = ServerFactory::create(_rpc_addr.second);
                auto msg_cb = std::bind(&Dispatcher::onMessage, _dispather.get(),
                                        std::placeholders::_1, std::placeholders::_2);
                _server->setMessageCallBack(msg_cb);
            }
            void start()
            {
                _server->start();
            }
            void registerService(const ServiceDescribe::ptr &service)
            {
                if (_enableRegistry)
                {
                    _registry_client->serviceRegistry(service->method(), _rpc_addr);
                }
                _router->registerService(service);
            }

        private:
            bool _enableRegistry;
            Address _rpc_addr;
            client::RegistryClient::ptr _registry_client;
            RpcRouter::ptr _router;
            Dispatcher::ptr _dispather;
            BaseServer::ptr _server;
        };

        class TopicServer
        {
        public:
            using ptr = std::shared_ptr<TopicServer>;
            TopicServer(int port)
                : _topic(std::make_shared<TopicManage>()),
                  _dispather(std::make_shared<Dispatcher>())
            {
                auto req_cb = std::bind(&TopicManage::onTopicService, _topic.get(),
                                        std::placeholders::_1, std::placeholders::_2);
                _dispather->registerHandler<TopicRequest>(MType::REQ_TOPIC, req_cb);

                auto msg_cb = std::bind(&Dispatcher::onMessage, _dispather.get(),
                                        std::placeholders::_1, std::placeholders::_2);
                _server = ServerFactory::create(port);
                _server->setMessageCallBack(msg_cb);

                auto close_cb = std::bind(&TopicServer::shutDownCallBack, this, std::placeholders::_1);
                _server->setCloseCallBack(close_cb);
            }
            void start()
            {
                _server->start();
            }

        private:
            void shutDownCallBack(const BaseConnection::ptr &conn)
            {
                _topic->shutDownConn(conn);
            }

        private:
            TopicManage::ptr _topic;
            Dispatcher::ptr _dispather;
            BaseServer::ptr _server;
        };
    }
}